#ifndef __SPHERICUBICMESH_H__
#define __SPHERICUBICMESH_H__

#include "../D3DRenderer/D3DRenderer.h"
using namespace Renderer;

#include "../Sphericubic/CelestialSystem.h"

namespace Sphericubic
{
	//--------------------------------------------------------------------
	//--------------------------------------------------------------------
	//--------------------------------------------------------------------

	class SphericubicMesh : public OrbitingObject
	{
	public:
		struct Vertex
		{
			float	m_afOnCube[3];	// location on original (-1, -1, -1)(1, 1, 1) cube.
			Vector3	m_oOnSphere;	// location on scaled final sphere not world transformed.
			Vector3	m_oFromCamDir;	// direction vector from camera position.
		};
		struct Face
		{
			Vertex*			m_pVertexes;
			unsigned short*	m_pIndexes;
			unsigned short	m_uIndexOffset;
			Vector3			m_oFaceNormal;
			Vector3			m_oBiNormals[2];
			Vector3			m_oQuadNormals[4];
			float			m_fBiCosines[2];

			bool IsFacingDir(const Vector3 _rCamPos, const Matrix& _rTransf);
		};
		typedef vector<Face*> FacePtrVec;

	public:
		SphericubicMesh(const EType& _eType, D3DRenderer& _rRenderer);
		~SphericubicMesh();

		virtual void Update(const float& _fTimeSpeed);

		bool Create(const unsigned int& _uSubdivisions, const float& _fScale);
		void Release();

		void SetPosition(const Vector3& _oPosition);
		void SetRotation(const Vector3& _oRotation); // in degree

		virtual void Begin();
		virtual void PreRender(LPD3DXEFFECT _pEffect, const D3DXPASS_DESC& _rPassDesc);
		virtual void Render();

		virtual void GetDepthRadiusModifiers(float& _fZNear, float& _fZFar) const;

		const unsigned int& GetFaceCount() const;
		const Face* GetFaces() const;

	protected:
		void CreateMeshVertices();
		void MorphToSphere();
		void UpdateBoundingSize();
		void SphereMapping(Vertex& _rVertex);
		void CreateMeshFaces();
		bool CreateVertexBuffer();

	protected:
		D3DRenderer&					m_rRenderer;
		LPDIRECT3DVERTEXBUFFER9			m_pVertexBuffer;
		LPDIRECT3DINDEXBUFFER9			m_pIndexBuffer;
		LPDIRECT3DVERTEXDECLARATION9	m_pVertexDecl;
		Matrix							m_oLocalRot;
		Matrix							m_oLocalPos;
		Matrix							m_oWorldTransf;
		Vector3							m_oRotation;
		Vector3							m_oPosition;

		FacePtrVec						m_vFaceToRenderList;
		Vertex*							m_pVertexes;
		Face*							m_pFaces;
		unsigned short*					m_pIndexes;
		unsigned int					m_uSubdivisions;
		unsigned int					m_uVerticesCount;
		unsigned int					m_uFacesCount;
		unsigned int					m_uIndexesCount;
		unsigned int					m_uVerticesPerRow;
		float							m_fScale;
	};
}

#endif // __SPHERICUBICMESH_H__